home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / archival / ftp / BFTP.312 / mbftp_tool.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-29  |  61.2 KB  |  2,335 lines

  1. /************************************************************************
  2.  *                                    *
  3.  *     Background File Transfer Program (BFTP)                *
  4.  *                                    *
  5.  *    Written at USC/Information Sciences Institute            *
  6.  *                                    *
  7.  *      BFTP is Public Domain, and may be used for any purpose as    *
  8.  *      long as this notice is not removed.  USC-ISI does not assume    *
  9.  *    any responsibility for the correctness, performance, or use    *
  10.  *    of this software.                        *
  11.  *                                    *
  12.  ************************************************************************/
  13.  
  14. /*  mbftp_tool.c
  15.  *
  16.  *  The "mbftptool" SunView user interface, is implemented in this module.
  17. */
  18.  
  19. #include <stdio.h>
  20. #include <ctype.h>
  21. #include <signal.h>
  22. #include <pwd.h>
  23. #include <sys/param.h>
  24. #include <sys/file.h>
  25. #include <sys/wait.h>
  26. #include <suntool/sunview.h>
  27.     /* includes <sunwindow/window_hs.h>, which includes <sys/time.h> */
  28. #include <sys/resource.h>
  29. #include <suntool/panel.h>
  30. #include <sunwindow/notify.h>
  31. #include <suntool/textsw.h>
  32.  
  33. /* FTS */
  34.  
  35. #include <netinet/in.h>    
  36. #include "fts.h"
  37.     /* bftp.h is included in fts.h */
  38.     
  39. extern FILE     *tracefp,  /* File to save trace of Telnet history */
  40.         *logfp;    /* File to compose message */
  41.  
  42. extern char
  43.   *crypt(),
  44.    bftp_dir[MAXPATHLEN],
  45.    def_user[L_cuserid],
  46.    def_mailbox[101],
  47.    def_hostname[80],
  48.    def_passwd[80],
  49.    def_dir[100];
  50.  
  51. extern boolean
  52.   conference,
  53.   parse_date(),
  54.   host_okay(),
  55.   read_req(),
  56.   write_req(),
  57.   empty_str();
  58.  
  59. extern int 
  60.   init_param_help(),
  61.   init_req_help(),
  62.   init_submit_help(),
  63.   find_errors(),
  64.   type_choice();
  65.  
  66. extern void 
  67.   copy_fileparams(),
  68.   display_dir_menu(),
  69.   display_login_menu(),
  70.   display_passw_menu(),
  71.   display_sfile_menu(),
  72.   dummy_event_proc(),
  73.   update_params(),
  74.   name_dotfile(),
  75.   hint_event_proc(),
  76.   init_user(),
  77.   init_host_menu(),
  78.   init_src_file_menu(),
  79.   init_passw_menu(),
  80.   init_login_menu(),
  81.   init_dir_menu(),
  82.   init_req(),
  83.   init_attr_lists(),
  84.   no_spaces(),
  85.   destroy_req_frame(),
  86.   init_rs_location(),
  87.   make_sumit_frame(),
  88.   rStorage_proc();
  89.     
  90. extern Menu dir_menu;
  91. extern Window popup_frame;
  92. extern Textsw fts_sw;
  93. extern Attr_avlist 
  94.   app_attr,
  95.   byte_attr,
  96.   form_attr,
  97.   mode_attr,
  98.   mult_attr,
  99.   stou_attr,
  100.   stru_attr,
  101.   type_attr,
  102.  
  103.   dir_attr,
  104.   file_attr,
  105.   host_attr,
  106.   login_attr,
  107.   pass_attr;
  108.  
  109. static short icon_image[] = {
  110. #include "bftp.icon"
  111. };
  112. DEFINE_ICON_FROM_IMAGE(bftp_icon, icon_image);
  113.  
  114. /* Required for tool_lib.c */
  115.  
  116. Frame tool_frame;
  117.  
  118. /* *********************** */
  119.  
  120.  
  121. static Panel_item 
  122.   pPass_item, 
  123.   pDone_item, 
  124.   pMsg_item;
  125. static Window pFrame, tool_panel;
  126.  
  127. extern Window popup_frame;
  128.  
  129. #define MAX_DEST 4    
  130.     /* due SunView limit on fd's */
  131.     /* Don't forget to update the help strings if this changed! */
  132. struct xxx {
  133.     char str[80];
  134.     };
  135. struct xxx hosts[MAX_DEST];
  136.  
  137. static int 
  138.   max_dest = MAX_DEST,    /* must be cut back to 3 for sunos3 */
  139.   tool_top = 0,     /* keep track of last window location */
  140.   prev_show_val = 0,    /* keep track of toggle value */
  141.   prev_useHost_val = 0, /* keep track of toggle value */
  142.   dFrame_y[MAX_DEST],    /* calculate position of each dest frame */
  143.   dest_pid[MAX_DEST],
  144.   dest_client[MAX_DEST];
  145. static boolean 
  146.   toolsetup = FALSE,
  147.   erase_dest_files = FALSE,
  148.   user_set_host[MAX_DEST];
  149.  
  150. static Textsw dStatus_sw[MAX_DEST];
  151. static Window
  152.   dest_frame[MAX_DEST], 
  153.   dest_panel[MAX_DEST];
  154.  
  155. /* Panel items */
  156.     
  157. extern Panel_item
  158.   /* Popup Window */
  159.     quitSW_item, keyword_item,
  160.     interval_item, tries_item, startTime_item, mailbox_item,
  161.   /* Parameters subwindow */
  162.     type_item, format_item, byteSize_item, stru_item, 
  163.       mode_item, stou_item, append_item, multiple_item;
  164.  
  165. Panel_item sFile_item;
  166. static Panel_item 
  167.   /* Commands subwindow */
  168.     quit_item, resetAll_item, 
  169.     submitAll_item, transferAll_item,
  170.     param_item, storage_item,
  171.   /* Parameters */
  172.     verbose_item, dist_item,
  173.       src_msg, sDir_item,
  174.     sHost_item, sLogin_item, sPass_item, sPassDef_msg,
  175.     conf_msg, cFile_item, cFileDef_msg,
  176.     useDHost_item, dShow_item,
  177.   /* Destination Subwindows */
  178.     dHost_item[MAX_DEST], 
  179.     dLogin_item[MAX_DEST], 
  180.     dLoginDef_msg[MAX_DEST],
  181.     dPass_item[MAX_DEST], 
  182.     dPassDef_msg[MAX_DEST],
  183.     dFile_item[MAX_DEST], 
  184.     dFileDef_msg[MAX_DEST],
  185.     dDir_item[MAX_DEST];
  186.  
  187.  
  188. #define SAME_AS_SRC "(same as Src)"
  189. #define SAME_AS_CONF "(same as Conf)"
  190. #define SAME_AS_HERE "(same as Here)"
  191. static char 
  192.   same_as_login[100], same_as_pass[100];
  193.  
  194. #define text_print(str) (void)textsw_insert(fts_sw, str, strlen(str))
  195. #define print_nofile(i)\
  196.   (void)textsw_insert(dStatus_sw[i], "Error: Source file not found\n", 29)
  197. #define set_status(i,str)\
  198.   panel_set(useDHost_item, PANEL_CHOICE_STRING,    i, str, 0)
  199. #define scroll_to_end(i)\
  200.   textsw_possibly_normalize(dStatus_sw[i],\
  201.                 (int)window_get(dStatus_sw[i],TEXTSW_LENGTH))
  202.  
  203. /* Table of item, corresponding hint text, and event_proc for optional
  204.    fields for which the default value is displayed as a hint:
  205. */
  206.  
  207. struct hint_record {
  208.      Panel_item *field_item, *msg_item;
  209.      void (*event_proc)();
  210.    } hint_list[] = {
  211.     &cFile_item,     &cFileDef_msg,       display_sfile_menu,
  212.     &sPass_item,    &sPassDef_msg,    display_passw_menu,
  213.     &dFile_item[0], &dFileDef_msg[0], display_sfile_menu,
  214.     &dLogin_item[0], &dLoginDef_msg[0],  display_login_menu,
  215.     &dPass_item[0], &dPassDef_msg[0], display_passw_menu,
  216.     &dFile_item[1], &dFileDef_msg[1], display_sfile_menu,
  217.     &dLogin_item[1], &dLoginDef_msg[1],  display_login_menu,
  218.     &dPass_item[1], &dPassDef_msg[1], display_passw_menu,
  219.     &dFile_item[2], &dFileDef_msg[2], display_sfile_menu,
  220.     &dLogin_item[2], &dLoginDef_msg[2],  display_login_menu,
  221.     &dPass_item[2], &dPassDef_msg[2], display_passw_menu,
  222.     &dFile_item[3], &dFileDef_msg[3], display_sfile_menu,
  223.     &dLogin_item[3], &dLoginDef_msg[3],  display_login_menu,
  224.     &dPass_item[3], &dPassDef_msg[3], display_passw_menu,
  225.     NULL,         NULL,           NULL 
  226.     };
  227.  
  228. #include "help_strings.h"
  229.  
  230. struct help_record {
  231.    union u_tag {
  232.      Panel_item *ip;
  233.      char    *cp;
  234.      } uval;
  235.    } helplist[1000];
  236.  
  237. static void
  238. init_help()
  239. {
  240.    int i = 0, j = 0;
  241.  
  242. #define set_ptr(item) helplist[i++].uval.ip = &item
  243. #define set_str(str) helplist[i++].uval.cp = str
  244. #define last_str() helplist[i++].uval.cp = NULL
  245.  
  246.    set_ptr(quit_item);
  247.    set_str(quit_help);
  248.    last_str();
  249.  
  250.    set_ptr(resetAll_item);
  251.    set_str("Reset stops any transfers marked with");
  252.    set_str("  a 'check' that are in progress.");
  253.    last_str();
  254.  
  255.    set_ptr(param_item);
  256.    set_str("ShowParams is used to display the file transfer parameters.");
  257.    set_str(toggle_help);
  258.    last_str();
  259.  
  260.    set_ptr(storage_item);
  261.    set_str(reqSW1_help);
  262.    set_str(reqSW2_help);
  263.    set_str(toggle_help);
  264.    last_str();
  265.  
  266.    i = init_req_help(i);
  267.  
  268.    for (j=0; j<MAX_DEST; j++) {
  269.       set_ptr(dHost_item[j]);
  270.       set_str(dhost_help);
  271.       last_str();
  272.  
  273.       set_ptr(dLogin_item[j]);
  274.       set_str(dlogin_help);
  275.       set_str(paren_help);
  276.       last_str();
  277.  
  278.       set_ptr(dPass_item[j]);
  279.       set_str(dpass_help);
  280.       set_str(paren_help);
  281.       last_str();
  282.  
  283.       set_ptr(dFile_item[j]);
  284.       set_str(dfile_help);
  285.       set_str(paren_help);
  286.       last_str();
  287.  
  288.       set_ptr(dDir_item[j]);
  289.       set_str(ddir1_help);
  290.       set_str(ddir2_help);
  291.       set_str(ddir3_help);
  292.       set_str(ddir4_help);
  293.       set_str(ddir5_help);
  294.       last_str();
  295.       }
  296.  
  297.    /* *** add conf_msg */
  298.  
  299.    set_ptr(cFile_item);
  300.    set_str("File name that will be used on the conference (destination) hosts.");
  301.    set_str(paren_help);
  302.    last_str();
  303.  
  304.    i = init_submit_help(i);
  305.  
  306.    set_ptr(dist_item);
  307.    set_str(
  308.    "The Distribution mode may be:");
  309.    set_str(
  310.    "  Src->Here->Dsts  Two part transfer: source to local host, followed by");
  311.    set_str(
  312.    "                       transfer from local host to checked destinations.");
  313.    set_str(
  314.    "  Here->Dsts       Transfer file from local host to checked destinations.");
  315.    last_str();
  316.  
  317.    set_ptr(pDone_item);
  318.    set_str("Click on 'Done' or type a carriage-return when the");
  319.    set_str("  local password has been typed.");
  320.    last_str();
  321.  
  322.    set_ptr(pPass_item);
  323.    set_str("The local password is the password of the user currently logged on.");
  324.    set_str("  It will be used as the default in the event that a password for");
  325.    set_str("  the source host or a destination host is not explicitly entered.");
  326.    set_str("  If no local password is supplied, the distribution mode will be");
  327.    set_str("  limited to 'Src->Dsts'.");
  328.    last_str();
  329.  
  330.    set_ptr(cFile_item);
  331.    set_str("File name that will be used on the conference (destination) hosts.");
  332.    set_str(paren_help);
  333.    last_str();
  334.  
  335.    set_ptr(useDHost_item);
  336.    set_str("Click a box to specify that a destination host be used when the");
  337.    set_str("  'Transfer', 'Submit', or 'Reset' command is clicked.  Click the");
  338.    set_str("  host name to display/undisplay the corresponding destination window.");
  339.    last_str();
  340.  
  341.    set_ptr(dShow_item);
  342.    set_str("Click the name of a host to display/undisplay the corresponding");
  343.    set_str("  destination window.  The status of the last transfer is shown");
  344.    set_str("  to the left of the host name.");
  345.    last_str();
  346.  
  347.    set_ptr(submitAll_item);
  348.    set_str("Submit is used to queue requests for all");
  349.    set_str("  destination hosts marked with a 'check'.");
  350.    last_str();
  351.  
  352.    set_ptr(transferAll_item);
  353.    set_str("Transfer causes the BFTP server to connect to the specified");
  354.    set_str("  hosts and perform the file transfer, while you wait, for");
  355.    set_str("  each destination marked with a 'check'.");
  356.    last_str();
  357.  
  358.    set_ptr(verbose_item);
  359.    set_str("The Verbose flag specifies that a detailed log of the");
  360.    set_str("  FTP commands be displayed in each destination status");
  361.    set_str("  window when the 'Transfer' command is selected.");
  362.    last_str();
  363.  
  364.    /* *** add src_msg */
  365.  
  366.    set_ptr(sHost_item);
  367.    set_str(sHost_help);
  368.    last_str();
  369.  
  370.    set_ptr(sLogin_item);
  371.    set_str(sLogin_help);
  372.    last_str();
  373.  
  374.    set_ptr(sPass_item);
  375.    set_str(sPass_help);
  376.    last_str();
  377.  
  378.    set_ptr(sFile_item);
  379.    set_str(sFile1_help);
  380.    set_str(sFile2_help);
  381.    last_str();
  382.  
  383.    set_ptr(sDir_item);
  384.    set_str(sDir1_help);
  385.    set_str(sDir2_help);
  386.    set_str(sDir3_help);
  387.    set_str(sDir4_help);
  388.    set_str(sDir5_help);
  389.    last_str();
  390.  
  391.    i = init_param_help(i);
  392.  
  393.    /* end the list */
  394.    helplist[i++].uval.ip = NULL;
  395. }
  396.  
  397. static void
  398. show_conf_fields(yes)
  399.    boolean yes;
  400. {
  401.    panel_set(conf_msg, PANEL_SHOW_ITEM, (yes)?TRUE:FALSE, 0);
  402.    panel_set(cFile_item, PANEL_SHOW_ITEM, (yes)?TRUE:FALSE, 0);
  403.    panel_set(cFileDef_msg, PANEL_SHOW_ITEM, 
  404.          (yes && !(strlen((char *)panel_get(cFile_item, PANEL_VALUE))))?
  405.            TRUE:FALSE, 
  406.          0);
  407. }
  408.  
  409. void
  410. show_dest_file(yes)
  411.    boolean yes;
  412. {
  413.    int i;
  414.  
  415.    if (conference &&
  416.        (!yes || !(int)panel_get(dist_item, PANEL_VALUE)))
  417.       show_conf_fields(yes);
  418.  
  419.    for (i=0;i<max_dest;i++) {
  420.       panel_set(dFile_item[i], PANEL_SHOW_ITEM, (yes)?TRUE:FALSE, 0);
  421.       panel_set(dFileDef_msg[i], PANEL_SHOW_ITEM, 
  422.         (yes && !strlen((char *)panel_get(dFile_item[i], PANEL_VALUE)))?
  423.                  TRUE:FALSE, 
  424.         0);
  425.       }
  426. }
  427.  
  428. show_src_fields(yes)
  429.    boolean yes;
  430. {
  431.   panel_set(sHost_item, PANEL_SHOW_ITEM, (yes)?TRUE:FALSE, 0);
  432.   panel_set(sLogin_item, PANEL_SHOW_ITEM, (yes)?TRUE:FALSE, 0);
  433.   panel_set(sPass_item, PANEL_SHOW_ITEM, (yes)?TRUE:FALSE, 0);
  434.   panel_set(sPassDef_msg, PANEL_SHOW_ITEM,
  435.         (yes && strlen(def_passwd) &&
  436.          !strlen((char *)panel_get(sPass_item, PANEL_VALUE)))?
  437.           TRUE:FALSE,
  438.         0);
  439. }
  440.  
  441. boolean
  442. host_matches(h1,h2)
  443.    char *h1, *h2;
  444. {
  445.    u_long addr1, addr2;
  446.  
  447.    return(((!strcmp(h1, h2)) ||
  448.        (resolve_name(h1, &addr1, 1) && 
  449.         resolve_name(h2, &addr2, 1) &&
  450.         addr1 == addr2)
  451.       )?TRUE:FALSE);
  452. }
  453.  
  454. static void
  455. src_to_dsts()
  456. {
  457.    int i;
  458.    char *cp, *src;
  459.  
  460.    src = (char *)panel_get(sHost_item, PANEL_VALUE);
  461.    for (i=0;i<max_dest;i++) {
  462.        cp = (char *)panel_get(dShow_item, PANEL_CHOICE_STRING, i);
  463.        panel_set(useDHost_item, 
  464.                  PANEL_TOGGLE_VALUE,     i, 
  465.              ((!empty_str(cp)) && !host_matches(cp, src))?TRUE:FALSE, 
  466.                  0);
  467.        }
  468.    if (conference)
  469.       panel_set(conf_msg, PANEL_LABEL_STRING, "Conf --", 0);
  470.    else
  471.       panel_set(storage_item, PANEL_SHOW_ITEM, TRUE, 0);
  472.    panel_set(submitAll_item, PANEL_SHOW_ITEM, TRUE, 0);
  473.    show_src_fields(TRUE);
  474.    if (!strcmp(def_dir,(char *)panel_get(sDir_item, PANEL_VALUE)))
  475.       panel_set(sDir_item, PANEL_VALUE,"",0);
  476.    panel_set(tool_panel, PANEL_CARET_ITEM, sFile_item, 0);
  477.  
  478.    prev_useHost_val = (int)panel_get(useDHost_item, PANEL_VALUE);
  479. } /* src_to_dsts */
  480.  
  481. static void
  482. dist_proc(item, value, event)
  483.    Panel_item item;
  484.    unsigned int value;
  485.    Event *event;
  486. {
  487.    int i;
  488.    char *cp, *src;
  489.  
  490.    switch (value) {
  491.       case 1: /* Here->Dsts */
  492.          panel_set(src_msg, PANEL_LABEL_STRING, "Here --", 0);
  493.      for (i=0;i<max_dest;i++) {
  494.         cp = (char *)panel_get(dShow_item, PANEL_CHOICE_STRING, i);
  495.         panel_set(useDHost_item, 
  496.               PANEL_TOGGLE_VALUE,     i, 
  497.               ((!empty_str(cp)) && !host_matches(cp, def_hostname))
  498.                 ?TRUE:FALSE, 
  499.               0);
  500.        }
  501.      panel_set(submitAll_item, PANEL_SHOW_ITEM, TRUE, 0);
  502.      show_src_fields(FALSE);
  503.      if (!strlen((char *)panel_get(sDir_item, PANEL_VALUE)))
  504.         panel_set(sDir_item, PANEL_VALUE, def_dir, 0);
  505.      show_conf_fields(FALSE);
  506.      break;
  507.       case 0: /* Src->Here->Dsts */
  508.          panel_set(src_msg, PANEL_LABEL_STRING, "Src --", 0);
  509.      src = (char *)panel_get(sHost_item, PANEL_VALUE);
  510.      for (i=0;i<max_dest;i++) {
  511.        cp = (char *)panel_get(dShow_item, PANEL_CHOICE_STRING, i);
  512.        panel_set(useDHost_item, 
  513.                  PANEL_TOGGLE_VALUE,     i, 
  514.              ((!empty_str(cp)) && !host_matches(cp, def_hostname) &&
  515.               !host_matches(cp, src))
  516.                 ?TRUE:FALSE, 
  517.                  0);
  518.        }
  519.      panel_set(submitAll_item, PANEL_SHOW_ITEM, FALSE, 0);
  520.      show_src_fields(TRUE);
  521.      if (!strcmp(def_dir,(char *)panel_get(sDir_item, PANEL_VALUE)))
  522.         panel_set(sDir_item, PANEL_VALUE,"",0);
  523.      if ((int)panel_get(append_item, PANEL_VALUE) ||
  524.                  !(int)panel_get(multiple_item, PANEL_VALUE))
  525.         show_conf_fields(TRUE);
  526.      break;
  527.        }
  528.    panel_set(tool_panel, PANEL_CARET_ITEM, sFile_item, 0);
  529.  
  530.    prev_useHost_val = (int)panel_get(useDHost_item, PANEL_VALUE);
  531. } /* dist_proc */
  532.  
  533. /* Routines used in Notify procs for commands subwindow */
  534.  
  535. static boolean
  536. new_y_positions()
  537. {
  538.    int i;
  539.    Rect *fRect = (Rect *)window_get(tool_frame, WIN_RECT, 0),
  540.        *rscreen;                  /* Rect for screen */
  541.    struct screen screen;
  542.  
  543.    if (tool_top != fRect->r_top) {
  544.       tool_top = fRect->r_top;
  545.  
  546.       /* get screen dimensions */
  547.       win_screenget((int)window_get(tool_frame, WIN_FD), &screen);
  548.       rscreen = &screen.scr_rect;
  549.  
  550.       for (i=0;i<max_dest;i++) {
  551.      dFrame_y[i] = fRect->r_height - 10 + i*65;
  552.          if ((fRect->r_top+dFrame_y[i]+150) > rscreen->r_height)
  553.         dFrame_y[i] = (i*65) - 30 - fRect->r_height;
  554.          }
  555.       return(TRUE);
  556.       }
  557.    return(FALSE);
  558. } /* new_y_positions */
  559.  
  560. void
  561. update_screen(src, dst, fil)
  562.    struct hostinfo *src, *dst;
  563.    struct fileinfo *fil;
  564. {
  565.    int i;
  566.    boolean show_file;
  567.  
  568.    panel_set(sHost_item, PANEL_VALUE, src->host, 0);
  569.    panel_set(sLogin_item, PANEL_VALUE, src->user, 0);
  570.    panel_set(sPass_item, PANEL_VALUE, src->passwd,
  571.        PANEL_LABEL_BOLD, (strlen(src->passwd))?TRUE:FALSE,
  572.     0);
  573.    panel_set(sDir_item, PANEL_VALUE, src->dir, 0);
  574.    panel_set(sFile_item, PANEL_VALUE, src->file, 0);
  575.  
  576.    /* copy source stuff into all of the dst structures and screens */
  577.  
  578.    /* Fill in the first destination host if it is blank */
  579.    if (!strlen((char *)panel_get(dHost_item[0], PANEL_VALUE))) {
  580.       panel_set(dHost_item[0], PANEL_VALUE, dst->host, 0);
  581.       panel_set(dShow_item,
  582.                 PANEL_CHOICE_STRING,    0,
  583.                         dst->host,
  584.             0);
  585.       panel_set(useDHost_item,
  586.             PANEL_TOGGLE_VALUE,        0, 
  587.                 !host_matches(dst->host, 
  588.                   (char *)panel_get(sHost_item, PANEL_VALUE))
  589.                         ?TRUE:FALSE,
  590.                0);
  591.       }
  592.  
  593.    (void)new_y_positions();
  594.    for (i = 0; i<max_dest ; i++) {
  595.       /* Show each current destination */
  596.       if ((int)panel_get(useDHost_item, PANEL_TOGGLE_VALUE, i)) {
  597.      panel_set(dShow_item, PANEL_TOGGLE_VALUE, i, TRUE, 0);
  598.      window_set(dest_frame[i], 
  599.          WIN_SHOW,     TRUE, 
  600.            WIN_X,        0,
  601.         WIN_Y,        dFrame_y[i],
  602.         0);
  603.          }
  604.  
  605.       /* set all destination parameters that are not the same as the default */
  606.       if (!strcmp(def_user, dst->user))  /* they're equal */
  607.      dst->user[0] = '\0';
  608.       panel_set(dLogin_item[i], PANEL_VALUE,dst->user, 0);
  609.       if (!strcmp(def_passwd, dst->passwd))  /* they're equal */
  610.      dst->passwd[0] = '\0';
  611.       panel_set(dPass_item[i], 
  612.         PANEL_VALUE,         dst->passwd,
  613.           PANEL_LABEL_BOLD,     (strlen(dst->passwd))?TRUE:FALSE,
  614.         0);
  615.       panel_set(dDir_item[i], PANEL_VALUE, dst->dir, 0);
  616.       if (!strcmp(src->file, dst->file)) /* they're equal */
  617.      dst->file[0] = '\0';
  618.       show_file = ((!fil->multflag) ||(fil->creation==APPE))?TRUE:FALSE;
  619.       panel_set(dFile_item[i], 
  620.         PANEL_VALUE,         dst->file, 
  621.           PANEL_SHOW_ITEM,     show_file,
  622.         0);
  623.       if (!strlen(dst->file))
  624.      panel_set(dFileDef_msg[i],
  625.            PANEL_SHOW_ITEM,        show_file,
  626.            0);
  627.       }
  628.  
  629.    update_params(fil);
  630.  
  631.    prev_show_val = (int)panel_get(dShow_item, PANEL_VALUE);
  632.    prev_useHost_val = (int)panel_get(useDHost_item, PANEL_VALUE);
  633. } /* update_screen */
  634.  
  635. #define SUBMIT_OK 20
  636. #define SUBMIT_BAD 21
  637. #define TRANSFER_OK 22
  638. #define TRANSFER_BAD 23
  639.  
  640. static Notify_value
  641. my_wait3_handler(me, pid, status, rusage)
  642.    int *me;
  643.    int pid;
  644.    union wait *status;
  645.    struct rusage *rusage;
  646. {
  647.    int i;
  648.     
  649.    if (WIFEXITED(*status)) {
  650.       for (i=0;i<max_dest;i++) if (&dest_client[i] == me) break;
  651.       if (i < max_dest) {
  652.          panel_set(useDHost_item,
  653.             PANEL_CHOICE_STRING,    i,
  654.             (status->w_retcode == TRANSFER_OK)?"Completed":
  655.             (status->w_retcode == SUBMIT_OK)?"Submitted":
  656.             "Failed",
  657.            0);
  658.      if (status->w_retcode == TRANSFER_OK ||
  659.          status->w_retcode == SUBMIT_OK)
  660.         erase_dest_files = TRUE;
  661.          }
  662.       return(NOTIFY_DONE);
  663.       }
  664.    return(NOTIFY_IGNORED);
  665. }
  666.  
  667. /* *** debugging stuff ***
  668. print_fds(str)
  669.    char *str;
  670. {
  671.    int nfds, fd;
  672.    
  673.    printf("%s:\n",str);
  674.    nfds = getdtablesize();
  675.    for (fd = 0; fd < nfds; fd++)
  676.     printf("%2d:%2d ", fd, fcntl(fd, F_GETFL,0));
  677.    printf("\n\n");
  678. }
  679. */
  680.  
  681. static void
  682. copy_src(src)
  683.    struct hostinfo *src;
  684. {
  685.    strcpy(src->host, 
  686.       ((int)panel_get(sHost_item, PANEL_SHOW_ITEM))?
  687.        (char *)panel_get(sHost_item, PANEL_VALUE):
  688.        def_hostname);
  689.    strcpy(src->user, 
  690.       ((int)panel_get(sLogin_item, PANEL_SHOW_ITEM))?
  691.        (char *)panel_get(sLogin_item, PANEL_VALUE):
  692.        def_user);
  693.    strcpy(src->passwd, 
  694.       ((int)panel_get(sPass_item, PANEL_SHOW_ITEM))?
  695.        (char *)panel_get(sPass_item, PANEL_VALUE):
  696.        def_passwd);
  697.    if (!strlen(src->passwd))
  698.       strcpy(src->passwd, def_passwd);
  699.    strcpy(src->dir, (char *)panel_get(sDir_item, PANEL_VALUE));
  700.    strcpy(src->file, (char *)panel_get(sFile_item, PANEL_VALUE));
  701.    src->port = DEFAULT_PORT;
  702.    src->acct[0] = '\0';
  703. } /* copy_src */
  704.  
  705. static void
  706. copy_dst(src, dst, index)
  707.    struct hostinfo *src, *dst;
  708.    int index;
  709. {
  710.    strcpy(dst->host, (char *)panel_get(dHost_item[index], PANEL_VALUE));
  711.    strcpy(dst->user, (char *)panel_get(dLogin_item[index], PANEL_VALUE));
  712.    if (!strlen(dst->user))
  713.          strcpy(dst->user, def_user);
  714.    strcpy(dst->passwd, (char *)panel_get(dPass_item[index], PANEL_VALUE));
  715.    if (!strlen(dst->passwd))
  716.          strcpy(dst->passwd, (strlen(def_passwd))?def_passwd:src->passwd);
  717.    strcpy(dst->dir, (char *)panel_get(dDir_item[index], PANEL_VALUE));
  718.    dst->port = DEFAULT_PORT;
  719.    dst->acct[0] = '\0';
  720.  
  721.    /* if visable, copy it, otherwise make it empty */
  722.    if ((int)panel_get(dFile_item[index], PANEL_SHOW_ITEM)) {
  723.          strcpy(dst->file, (char *)panel_get(dFile_item[index], PANEL_VALUE));
  724.      if (!strlen(dst->file)) {
  725.         if (conference)
  726.            strcpy(dst->file, (char *)panel_get(cFile_item, PANEL_VALUE));
  727.         if (!strlen(dst->file))
  728.            strcpy(dst->file, src->file);
  729.         }
  730.      }
  731.    else
  732.          dst->file[0] = '\0';
  733. } /* copy_dst */
  734.  
  735. /* Used in tool_lib.c */
  736. void
  737. copy_screen(src, dst, fil)
  738.    struct hostinfo *src, *dst;
  739.    struct fileinfo *fil;
  740. {
  741.    copy_src(src);
  742.    copy_dst(src, dst, 0);    /* copy the first destination frame */
  743.    copy_fileparams(&fil);
  744. }
  745.  
  746. static boolean
  747. write_dotfile(filename)
  748.    char *filename;
  749. {
  750.    FILE *xxx, *stream;
  751.    char temp[60], dotfile[100];
  752.  
  753.    /* check that file exists */
  754.    if (xxx = fopen(filename,"r")) {
  755.       fclose(xxx);
  756.    
  757.       sprintf(temp, "sum %s", filename); 
  758.       if (stream = popen(temp,"r")) {
  759.      fgets(temp,sizeof(temp),stream);
  760.      pclose(stream);
  761.      name_dotfile(filename, dotfile);
  762.      if (xxx = fdopen(open(dotfile, (O_WRONLY|O_CREAT), 0600), "w")) {
  763.         fputs(temp, xxx);
  764.         fclose(xxx);
  765.         return(TRUE);
  766.         }
  767.          }
  768.       }
  769.    return(FALSE);
  770. }
  771.  
  772. static boolean
  773. make_dotfiles(src, multflag)
  774.    struct hostinfo *src;
  775.    boolean multflag;
  776. {
  777.    int i;
  778.    FILE *xxx, *stream;
  779.    char temp[100], filespec[100], filename[100];
  780.  
  781.    if (!strlen(src->dir) || src->dir[0] != '/') {
  782.       strcpy(filespec, getenv("HOME"));
  783.       if ((i = strlen(filespec)) && filespec[i-1] != '/')
  784.      strcat(filespec, "/");
  785.       }
  786.    else
  787.       filespec[0] = '\0';
  788.    strcat(filespec, src->dir);
  789.    if ((i = strlen(filespec)) && filespec[i-1] != '/')
  790.       strcat(filespec, "/");
  791.    strcat(filespec, src->file);
  792.  
  793.    if (!multflag)
  794.       return(write_dotfile(filespec));
  795.    else {
  796.       sprintf(temp, "ls -1 %s", filespec); 
  797.       if (stream = popen(temp,"r")) {
  798.      fgets(temp,sizeof(temp),stream);
  799.      while (i = strlen(temp)) {
  800.        /* for each file that matches */
  801.        temp[i-1] = '\0'; /* get rid of LF */
  802.        strcpy(filename, temp);
  803.        temp[0] = '\0';
  804.        if (!write_dotfile(filename)) {
  805.           pclose(stream);
  806.           return(FALSE);
  807.           }
  808.        fgets(temp,sizeof(temp),stream);
  809.            }
  810.      pclose(stream);
  811.          }
  812.       }
  813.    return(TRUE);
  814. } /* make_dotfiles */
  815.  
  816. Notify_value
  817. my_pipe_reader(me, fd)
  818.    int *me, fd;
  819. {
  820.    int i, n;
  821.    char c[2];
  822.  
  823.    for (i=0;i<max_dest;i++) if (&dest_client[i] == me) break;
  824.    if (i < max_dest)
  825.       while (fd_select(fd))
  826.          if (n = read(fd, c, 1)) {
  827.         c[1] = '\0';
  828.         (void)textsw_insert(dStatus_sw[i], c, n);
  829.         if (c[0] == '\n')
  830.            break;
  831.         }
  832.      else {
  833.         if (close(fd) == -1)
  834.            perror("close0");
  835.         dest_pid[i] = 0;
  836.         (void) notify_set_input_func(&dest_client[i],
  837.                                       NOTIFY_FUNC_NULL, fd);
  838.         break;
  839.         }
  840.    return(NOTIFY_DONE);
  841. } /* my_pipe_reader */
  842.  
  843. static void
  844. transfer_going(i)
  845.    int i;
  846. {
  847.    (void)textsw_insert(dStatus_sw[i], "Transfer already in progress!\n", 30);
  848.    set_status(i, "Running");
  849. }
  850.  
  851. static Notify_value
  852. part1_wait_handler(me, p_id, status, rusage)
  853.    int *me;
  854.    int p_id;
  855.    union wait *status;
  856.    struct rusage *rusage;
  857. {
  858.    struct server_struct ssh, dsh;
  859.    struct fileinfo fil;
  860.    char temp[100], path[100];
  861.    boolean verbose,
  862.          no_dotfile = TRUE;
  863.    int fd, nfds, retcode, pid, fildes[2];
  864.    int i, index;
  865.     
  866.    if (WIFEXITED(*status)) {
  867.       for (index=0;index<max_dest;index++) 
  868.      if (&dest_client[index] == me) 
  869.         break;
  870.       if (index < max_dest) {
  871.      dest_pid[index] = 0;
  872.      if (status->w_retcode != TRANSFER_OK)
  873.         set_status(index, "Failed");
  874.      else { /* TRANSFER_OK */
  875.         verbose = (int)panel_get(verbose_item, PANEL_VALUE);
  876.         copy_fileparams(&fil);
  877.         strcpy(ssh.h.host, def_hostname);
  878.         strcpy(ssh.h.dir, def_dir);
  879.         strcpy(ssh.h.user, def_user);
  880.         strcpy(ssh.h.passwd, def_passwd);
  881.         if ((int)panel_get(cFile_item, PANEL_SHOW_ITEM))
  882.            strcpy(ssh.h.file, (char *)panel_get(cFile_item, PANEL_VALUE));
  883.         if (!strlen(ssh.h.file))
  884.            strcpy(ssh.h.file, (char *)panel_get(sFile_item, PANEL_VALUE));
  885.         ssh.h.port = DEFAULT_PORT;
  886.         ssh.h.acct[0] = '\0';
  887.         if (make_dotfiles(&ssh.h, fil.multflag))
  888.            no_dotfile = FALSE;
  889.  
  890.         for (i = index;i<max_dest;i++) 
  891.            if ((int)panel_get(useDHost_item, PANEL_TOGGLE_VALUE, i)) {
  892.           scroll_to_end(i);
  893.           if (dest_pid[i]) 
  894.              transfer_going(i);
  895.           else {
  896.             copy_dst(&ssh.h, &dsh.h, i);
  897.             if (find_errors(dStatus_sw[i], &ssh.h, &dsh.h, &fil))
  898.                set_status(i, "Failed");
  899.             else {
  900.                if (pipe(fildes) == -1) {
  901.               sprintf(temp,"pipe %d",i);
  902.               perror(temp);
  903.               exit(1);
  904.               }
  905.                (void) notify_set_input_func(&dest_client[i], 
  906.                             my_pipe_reader, fildes[0]);
  907.                if (pid = fork()) {
  908.               (void)close(fildes[1]);
  909.               if (pid == -1) {
  910.                  perror("fork");
  911.                  (void)close(fildes[0]);
  912.                  (void) notify_set_input_func(&dest_client[i],
  913.                      NOTIFY_FUNC_NULL, fildes[0]);
  914.                  }
  915.               else {
  916.                  dest_pid[i] = pid;
  917.                  (void)notify_set_wait3_func(&dest_client[i],
  918.                      my_wait3_handler, pid);
  919.                  set_status(index, "Part2...");
  920.                  }
  921.                  }
  922.                else { /* this is the child process */
  923.              if (dup2(fildes[1], 1) == -1) {
  924.                 perror("dup2");
  925.                 (void)close(fildes[1]);
  926.                 exit(1);
  927.                 }
  928.  
  929.              nfds = getdtablesize(); /* Get max number of fd's */
  930.              (void)close(0);    /* Close all fd's except fd 1 */
  931.              for (fd = 2; fd < nfds; fd++)
  932.                 (void)close(fd);
  933.  
  934.              if (conference)
  935.                 if (no_dotfile ||
  936.                 (strlen(dsh.h.file) && 
  937.                  strcmp(dsh.h.file, ssh.h.file)))
  938.                    /* they are not the same */
  939.                    conference = FALSE; 
  940.                              /* just in the child process */
  941.  
  942.              tracefp = (verbose)?stdout:NULL;
  943.              logfp = stdout;
  944.  
  945.              format_time(0, temp);
  946.              fprintf(logfp,"\n  %s: starting...\n\n", temp);
  947.     
  948.              sprintf(path,"%s%d",REQPREFIX, time(NULL)+i);
  949.              sprintf(temp, "%s.req", path);
  950.             
  951.              retcode = xfer(&ssh, &dsh, &fil, temp, NULL);
  952.      
  953.              sprintf(temp,"rm %s.list 1> /dev/null 2>&1\n", path);
  954.              system(temp);
  955.  
  956.              format_time(0, temp);
  957.              fprintf(logfp,"\n  %s: completed %ssuccessfully.\n\n", 
  958.                  temp, (retcode == OK)?"":"un");
  959.              fflush(logfp);
  960.              exit((retcode == OK)?TRANSFER_OK:TRANSFER_BAD);
  961.                  }
  962.                }
  963.             }
  964.         }
  965.         }
  966.          }
  967.       return(NOTIFY_DONE);
  968.       }
  969.    return(NOTIFY_IGNORED);
  970. } /* part1_wait_handler */
  971.  
  972. static void
  973. part1_fork(index)
  974.    int index;
  975. {
  976.    struct server_struct ssh, dsh;
  977.    struct fileinfo fil;
  978.    char temp[100], path[100];
  979.    int fd, nfds, retcode, pid, fildes[2];
  980.    boolean verbose;
  981.  
  982.    scroll_to_end(index);
  983.    if (dest_pid[index])
  984.       transfer_going(index);
  985.  
  986.    verbose = (int)panel_get(verbose_item, PANEL_VALUE);
  987.  
  988.    copy_fileparams(&fil);
  989.    copy_src(&ssh.h);
  990.  
  991.    strcpy(dsh.h.host, def_hostname);
  992.    strcpy(dsh.h.dir, def_dir);
  993.    strcpy(dsh.h.user, def_user);
  994.    strcpy(dsh.h.passwd, def_passwd);
  995.    dsh.h.port = DEFAULT_PORT;
  996.    dsh.h.acct[0] = '\0';
  997.  
  998.    /* if visable, copy it, otherwise make it empty */
  999.    if ((int)panel_get(cFile_item, PANEL_SHOW_ITEM)) {
  1000.       strcpy(dsh.h.file, (char *)panel_get(cFile_item, PANEL_VALUE));
  1001.       if (!strlen(dsh.h.file)) {
  1002.      if ((int)panel_get(dFile_item[index], PANEL_SHOW_ITEM))
  1003.         strcpy(dsh.h.file, 
  1004.            (char *)panel_get(dFile_item[index], PANEL_VALUE));
  1005.      if (!strlen(dsh.h.file))
  1006.         strcpy(dsh.h.file, ssh.h.file);
  1007.          }
  1008.       }
  1009.    else
  1010.       dsh.h.file[0] = '\0';
  1011.  
  1012.    if (find_errors(dStatus_sw[index], &ssh.h, &dsh.h, &fil)) {
  1013.       set_status(index, "Failed");
  1014.       return;
  1015.       }
  1016.  
  1017.    if (pipe(fildes) == -1) {
  1018.          sprintf(temp,"pipe %d",index);
  1019.          perror(temp);
  1020.      exit(1);
  1021.          }
  1022.    (void) notify_set_input_func(&dest_client[index], 
  1023.                    my_pipe_reader, fildes[0]);
  1024.    if (pid = fork()) {
  1025.          (void)close(fildes[1]);
  1026.          if (pid == -1) {
  1027.             perror("fork");
  1028.         (void)close(fildes[0]);
  1029.         (void) notify_set_input_func(&dest_client[index],
  1030.                      NOTIFY_FUNC_NULL, fildes[0]);
  1031.         return;
  1032.         }
  1033.      dest_pid[index] = pid;
  1034.      (void)notify_set_wait3_func(&dest_client[index],
  1035.                      part1_wait_handler, pid);
  1036.      set_status(index, "Part1...");
  1037.          }
  1038.    else { /* this is the child process */
  1039.          if (dup2(fildes[1], 1) == -1) {
  1040.         perror("dup2");
  1041.         (void)close(fildes[1]);
  1042.         exit(1);
  1043.         }
  1044.  
  1045.      nfds = getdtablesize();        /* Get max number of fd's */
  1046.      (void)close(0);        /* Close all fd's except fd 1 */
  1047.      for (fd = 2; fd < nfds; fd++)
  1048.         (void)close(fd);
  1049.  
  1050.      conference = FALSE;
  1051.         /* don't need dot-file on src->here transfer */
  1052.  
  1053.      tracefp = (verbose)?stdout:NULL;
  1054.      logfp = stdout;
  1055.  
  1056.      format_time(0, temp);
  1057.      fprintf(logfp,"\n  %s: starting...\n\n", temp);
  1058.     
  1059.      sprintf(path,"%s%d",REQPREFIX, time(NULL));
  1060.      sprintf(temp, "%s.req", path);
  1061.      
  1062.      retcode = xfer(&ssh, &dsh, &fil, temp, NULL);
  1063.      
  1064.      sprintf(temp,"rm %s.list 1> /dev/null 2>&1\n", path);
  1065.      system(temp);
  1066.  
  1067.      format_time(0, temp);
  1068.      fprintf(logfp,"\n  %s: completed %ssuccessfully.\n\n", temp, 
  1069.             (retcode == OK)?"":"un");
  1070.      fflush(logfp);
  1071.      exit((retcode == OK)?TRANSFER_OK:TRANSFER_BAD);
  1072.          }
  1073. } /* part1_fork */
  1074.  
  1075. static void
  1076. close_dframe(i)
  1077.    int i;
  1078. {
  1079.    boolean blank = FALSE, set, bad = FALSE;
  1080.    char *cp;
  1081.     
  1082.    /* If the frame is open, copy the host name and close it */
  1083.    if ((int)window_get(dest_frame[i], WIN_SHOW)) {
  1084.       cp = (char *)panel_get(dHost_item[i], PANEL_VALUE);
  1085.       set = (int)panel_get(useDHost_item, PANEL_TOGGLE_VALUE, i);
  1086.       if (!strlen(cp)) {
  1087.      blank = TRUE;
  1088.      user_set_host[i] = FALSE;
  1089.          }
  1090.       else
  1091.      if (strcmp(cp, (char *)panel_get(dShow_item, PANEL_CHOICE_STRING,i)))
  1092.         /* they don't match */
  1093.         if (!host_okay(cp))
  1094.            bad = TRUE;
  1095.         else
  1096.            user_set_host[i] = TRUE;
  1097.       panel_set(useDHost_item,
  1098.               /* Decide whether to mark the dest host "inuse" */
  1099.         PANEL_TOGGLE_VALUE,    i, 
  1100.                     ((!set) || blank || bad)? FALSE:TRUE,
  1101.         /* Clear the status */
  1102.             PANEL_CHOICE_STRING,    i,
  1103.                     (set && bad)?"Bad Host":" ",
  1104.         0);
  1105.       /* Make the dest window disappear */
  1106.       window_set(dest_frame[i], WIN_SHOW, FALSE, 0);
  1107.       panel_set(dShow_item,
  1108.             PANEL_CHOICE_STRING,    i,
  1109.                     (blank || bad)?" ":cp,
  1110.               PANEL_TOGGLE_VALUE,     i,
  1111.                     FALSE,
  1112.            0);
  1113.       }
  1114. } /* close_dframe */
  1115.  
  1116. /* Notify Procs for the Commands Subwindow */
  1117.  
  1118. static Notify_value
  1119. clear_dest(frame, status)
  1120.    Frame frame;
  1121.    Destroy_status status;
  1122. {
  1123.    int i;
  1124.    
  1125.    for (i=0;i<max_dest;i++) 
  1126.        if (dest_frame[i] == frame) {
  1127.        close_dframe(i);
  1128.        break;
  1129.        }
  1130.    prev_useHost_val = (int)panel_get(useDHost_item, PANEL_VALUE);
  1131.    prev_show_val = (int)panel_get(dShow_item, PANEL_VALUE);
  1132. }
  1133.  
  1134. static void
  1135. reset_all(item, event)
  1136.    Panel_item item;
  1137.    Event *event;
  1138. {
  1139.    int i;
  1140.  
  1141.    for (i=0;i<max_dest;i++) {
  1142.       if ((int)panel_get(useDHost_item, PANEL_TOGGLE_VALUE, i))
  1143.          if (dest_pid[i]) {
  1144.         kill(dest_pid[i], SIGKILL);
  1145.         dest_pid[i] = 0;
  1146.         set_status(i, "Reset");
  1147.         }
  1148.       }
  1149. }
  1150.  
  1151. static void
  1152. set_buttons(status)
  1153.    boolean status;
  1154. {
  1155.    /* these items use the popup_frame and must be cleared */
  1156.    panel_set(transferAll_item, PANEL_SHOW_ITEM, status, 0);
  1157.    panel_set(submitAll_item, PANEL_SHOW_ITEM, status, 0);
  1158. /* ***   panel_set(explain_item, PANEL_SHOW_ITEM, status, 0); */
  1159.  
  1160.    if (!conference) {
  1161.       panel_set(storage_item, PANEL_SHOW_ITEM, status, 0);
  1162.       if (!status)
  1163.      destroy_req_frame();
  1164.       }
  1165. }
  1166.  
  1167. void
  1168. quit_popup(item, event)
  1169.    Panel_item item;
  1170.    Event *event;
  1171. {
  1172.    reset_all(0,0);
  1173.    window_destroy(popup_frame);
  1174.    set_buttons(TRUE);
  1175. }
  1176.  
  1177. static struct reqinfo req;
  1178.  
  1179. void
  1180. do_submit(item, event)
  1181.    Panel_item item;
  1182.    Event *event;
  1183. {
  1184.    FILE *xxx;
  1185.    struct server_struct ssh, dsh;
  1186.    struct fileinfo fil;
  1187.    char temp[100], path[100], timestr[100];
  1188.    boolean verbose;
  1189.    int i, fd, nfds, retcode, pid, fildes[2];
  1190.    u_long now, start;
  1191.  
  1192.    now = time(NULL);
  1193.  
  1194.    /* parse the start time */
  1195.    strcpy(timestr, (char *)panel_get(startTime_item, PANEL_VALUE));
  1196.    if (empty_str(timestr))
  1197.       start = now;
  1198.    else if (!parse_date(timestr, &start)) {
  1199.       sprintf(temp," Date '%s' not parsed.\n",timestr);
  1200.       text_print(temp);
  1201.       panel_set(startTime_item, PANEL_VALUE, "now", 0);
  1202.       return;
  1203.       }
  1204.  
  1205.    /* copy request parameters from screen */
  1206.    init_req(&req);
  1207.    strcpy(req.rpasswd, (char *)panel_get(keyword_item, PANEL_VALUE));
  1208.    if (empty_str(req.rpasswd)) req.rpasswd[0] = '\0';
  1209.    strcpy(req.mailbox, (char *)panel_get(mailbox_item, PANEL_VALUE));
  1210.    if (!mailbox_ok(req.mailbox, temp)) {
  1211.       text_print(" Invalid mailbox.\n");
  1212.       panel_set(mailbox_item, PANEL_VALUE, def_mailbox, 0);
  1213.       return;
  1214.       }
  1215.    req.interval = atoi((char *)panel_get(interval_item, PANEL_VALUE));
  1216.    req.ntries = atoi((char *)panel_get(tries_item, PANEL_VALUE));
  1217.  
  1218.    verbose = (int)panel_get(verbose_item, PANEL_VALUE);
  1219.    copy_fileparams(&fil);
  1220.    copy_src(&ssh.h);
  1221.  
  1222.    for (i=0;i<max_dest;i++) {
  1223.       close_dframe(i);
  1224.       if ((int)panel_get(useDHost_item, PANEL_TOGGLE_VALUE, i)) {
  1225.      scroll_to_end(i);
  1226.      if (dest_pid[i])
  1227.         transfer_going(i);
  1228.      else {
  1229.         copy_dst(&ssh.h, &dsh.h, i);
  1230.         if (find_errors(dStatus_sw[i], &ssh.h, &dsh.h, &fil)) {
  1231.            set_status(i, "Failed");
  1232.            }
  1233.         else {
  1234.            if (pipe(fildes) == -1) {
  1235.           sprintf(temp,"pipe %d",i);
  1236.           perror(temp);
  1237.           exit(1);
  1238.           }
  1239.            (void) notify_set_input_func(&dest_client[i], 
  1240.                    my_pipe_reader, fildes[0]);
  1241.            if (pid = fork()) {
  1242.           (void)close(fildes[1]);
  1243.           if (pid == -1) {
  1244.                 perror("fork");
  1245.             (void)close(fildes[0]);
  1246.             (void)notify_set_input_func(&dest_client[i],
  1247.                      NOTIFY_FUNC_NULL, fildes[0]);
  1248.                 }
  1249.           else {
  1250.                 dest_pid[i] = pid;
  1251.             (void)notify_set_wait3_func(&dest_client[i],
  1252.                      my_wait3_handler, pid);
  1253.             set_status(i, "Running");
  1254.                 }
  1255.           }
  1256.            else { /* this is the child process */
  1257.           if (dup2(fildes[1], 1) == -1) {
  1258.                 perror("dup2");
  1259.             (void)close(fildes[1]);
  1260.             exit(1);
  1261.                 }
  1262.  
  1263.           nfds = getdtablesize();     /* Get max number of fd's */
  1264.           (void)close(0);        /* Close all fd's except fd 1 */
  1265.           for (fd = 2; fd < nfds; fd++)
  1266.             (void)close(fd);
  1267.  
  1268.           if (conference)
  1269.                if (strlen(dsh.h.file) && strcmp(dsh.h.file, ssh.h.file))
  1270.                        /* they are not the same */
  1271.              conference = FALSE; /* just in the child process */
  1272.  
  1273.           sprintf(path, "%s%d", REQPREFIX, start+i);
  1274.  
  1275.           sprintf(temp, "%s.req", path);
  1276.           sprintf(req.mailfile, "%s.msg", path);
  1277.           sprintf(req.cmdfile, "%s.cmd", path);
  1278.           write_req(temp, &req, &ssh.h, &dsh.h, &fil, NULL);
  1279.  
  1280.           sprintf(temp, "%s.cmd", path);
  1281.           xxx = fdopen(open(temp, (O_WRONLY|O_CREAT), 0600), "w");
  1282.           fprintf(xxx,  "%s -v %s %s.req\n", 
  1283.                  FXPATH, (conference)?"-c":"", path);
  1284.           fclose(xxx);
  1285.  
  1286.           sprintf(temp, "%s.msg", path);
  1287.           xxx = fdopen(open(temp, (O_WRONLY|O_CREAT), 0600), "w");
  1288.           queue_req(&req, (now > start) ? now : start, temp);
  1289.           print_req(xxx, &req, &ssh.h, &dsh.h, &fil, FALSE);
  1290.           fprintf(xxx, "\n%s\n", temp);
  1291.           fclose(xxx);
  1292.           strcat(temp, "\n\n");
  1293.           printf(temp);
  1294.           exit(SUBMIT_OK);
  1295.           }
  1296.            }
  1297.         }
  1298.      }
  1299.       }
  1300.  
  1301.    window_destroy(popup_frame);
  1302.    set_buttons(TRUE);
  1303.    prev_useHost_val = (int)panel_get(useDHost_item, PANEL_VALUE);
  1304.    prev_show_val = (int)panel_get(dShow_item, PANEL_VALUE);
  1305. } /* do_submit */
  1306.  
  1307. static void
  1308. transfer_all(item, event)
  1309.    Panel_item item;
  1310.    Event *event;
  1311. {
  1312.    struct server_struct ssh, dsh;
  1313.    struct fileinfo fil;
  1314.    char temp[100], path[100];
  1315.    int i, fd, nfds, retcode, pid, fildes[2];
  1316.    boolean verbose,
  1317.       no_dotfile = TRUE,
  1318.       two_step = (conference && strlen(def_passwd) &&
  1319.           (!(int)panel_get(dist_item, PANEL_VALUE)))?TRUE:FALSE;
  1320.    u_long now;
  1321.  
  1322.    destroy_req_frame();
  1323.    if (two_step) {
  1324.       for (i=0;i<max_dest;i++) {
  1325.      if ((int)panel_get(useDHost_item, PANEL_TOGGLE_VALUE, i))
  1326.         set_status(i, " ");
  1327.      close_dframe(i);
  1328.          }
  1329.       for (i=0;i<max_dest;i++) 
  1330.       if ((int)panel_get(useDHost_item, PANEL_TOGGLE_VALUE, i)) {
  1331.          part1_fork(i);
  1332.                break;
  1333.          }
  1334.       }
  1335.    else {
  1336.       now = time(NULL);
  1337.       verbose = (int)panel_get(verbose_item, PANEL_VALUE);
  1338.       copy_src(&ssh.h);
  1339.       copy_fileparams(&fil);
  1340.       if (conference && 
  1341.       (strlen(def_passwd) ||
  1342.        (!strcmp(ssh.h.user, def_user) &&
  1343.         host_matches(ssh.h.host, def_hostname)
  1344.       )))
  1345.      if (make_dotfiles(&ssh.h, fil.multflag))
  1346.         no_dotfile = FALSE;
  1347.       for (i=0;i<max_dest;i++) {
  1348.          close_dframe(i);
  1349.      if ((int)panel_get(useDHost_item, PANEL_TOGGLE_VALUE, i)) {
  1350.         scroll_to_end(i);
  1351.         if (dest_pid[i])
  1352.            transfer_going(i);
  1353.         else {
  1354.            copy_dst(&ssh.h, &dsh.h, i);
  1355.            if (find_errors(dStatus_sw[i], &ssh.h, &dsh.h, &fil))
  1356.           set_status(i, "Failed");
  1357.            else {
  1358.           if (pipe(fildes) == -1) {
  1359.              sprintf(temp,"pipe %d",i);
  1360.              perror(temp);
  1361.              exit(1);
  1362.              }
  1363.           (void) notify_set_input_func(&dest_client[i], 
  1364.                    my_pipe_reader, fildes[0]);
  1365.           if (pid = fork()) {
  1366.              (void)close(fildes[1]);
  1367.              if (pid == -1) {
  1368.                 perror("fork");
  1369.             (void)close(fildes[0]);
  1370.             (void)notify_set_input_func(&dest_client[i],
  1371.                      NOTIFY_FUNC_NULL, fildes[0]);
  1372.                 }
  1373.              else {
  1374.                 dest_pid[i] = pid;
  1375.             (void)notify_set_wait3_func(&dest_client[i],
  1376.                      my_wait3_handler, pid);
  1377.             set_status(i, "Running");
  1378.                 }
  1379.              }
  1380.           else { /* this is the child process */
  1381.              if (dup2(fildes[1], 1) == -1) {
  1382.                 perror("dup2");
  1383.             (void)close(fildes[1]);
  1384.             exit(1);
  1385.                 }
  1386.  
  1387.              nfds = getdtablesize();     /* Get max number of fd's */
  1388.              (void)close(0);        /* Close all fd's except fd 1 */
  1389.              for (fd = 2; fd < nfds; fd++)
  1390.                 (void)close(fd);
  1391.  
  1392.              if (conference)
  1393.                 if (no_dotfile || 
  1394.                 ((strlen(dsh.h.file) &&
  1395.                   strcmp(dsh.h.file, ssh.h.file))))
  1396.                    /* they are not the same */
  1397.                conference = FALSE; /* just in the child process */
  1398.  
  1399.              tracefp = (verbose)?stdout:NULL;
  1400.              logfp = stdout;
  1401.  
  1402.              format_time(0, temp);
  1403.              fprintf(logfp,"\n  %s: starting...\n\n", temp);
  1404.     
  1405.              sprintf(path,"%s%d",REQPREFIX, now+i);
  1406.              sprintf(temp, "%s.req", path);
  1407.      
  1408.              retcode = xfer(&ssh, &dsh, &fil, temp, NULL);
  1409.      
  1410.              sprintf(temp,"rm %s.list 1> /dev/null 2>&1\n", path);
  1411.              system(temp);
  1412.  
  1413.              format_time(0, temp);
  1414.              fprintf(logfp,
  1415.                  "\n  %s: completed %ssuccessfully.\n\n", temp, 
  1416.                  (retcode == OK)?"":"un");
  1417.              fflush(logfp);
  1418.              exit((retcode == OK)?TRANSFER_OK:TRANSFER_BAD);
  1419.              }
  1420.           }
  1421.            }
  1422.         }
  1423.          }
  1424.       }
  1425.    prev_useHost_val = (int)panel_get(useDHost_item, PANEL_VALUE);
  1426.    prev_show_val = (int)panel_get(dShow_item, PANEL_VALUE);
  1427. } /* transfer_all */
  1428.  
  1429. static void
  1430. sFile_event_proc(item, event)
  1431.      Panel_item item;
  1432.      Event *event;
  1433. {
  1434.    int i;
  1435.  
  1436.    if (erase_dest_files && event_is_ascii(event)) {
  1437.       erase_dest_files = FALSE;
  1438.       /* delete all of the dest files */
  1439.       for (i=0;i<max_dest;i++) {
  1440.      panel_set(dFile_item[i], PANEL_VALUE, "", 0);
  1441.      panel_set(dFileDef_msg[i], PANEL_SHOW_ITEM, TRUE, 0);
  1442.          }
  1443.       if (conference) {
  1444.      panel_set(cFile_item, PANEL_VALUE, "", 0);
  1445.      if ((int)panel_get(cFile_item, PANEL_SHOW_ITEM))
  1446.         panel_set(cFileDef_msg, PANEL_SHOW_ITEM, TRUE, 0);
  1447.          }
  1448.       }
  1449.    no_spaces(item, event);
  1450. } /* sFile_event_proc */
  1451.  
  1452. make_dest_frames()
  1453. {
  1454.    int i, row;
  1455.  
  1456.    (void)new_y_positions();
  1457.    for (i=0;i<max_dest;i++) {
  1458.       row = 0;
  1459.       user_set_host[i] = FALSE;
  1460.  
  1461.       dest_frame[i] = window_create(tool_frame, FRAME,
  1462.            WIN_X,    0,
  1463.         WIN_Y,    dFrame_y[i],
  1464.         FRAME_NO_CONFIRM,     TRUE,
  1465.         FRAME_DONE_PROC,      clear_dest,
  1466.         0);
  1467.     
  1468.       dest_panel[i] = window_create(dest_frame[i], PANEL,
  1469.            0);
  1470.       dHost_item[i] = panel_create_item(dest_panel[i], PANEL_TEXT,
  1471.            PANEL_LABEL_X,        ATTR_COL(2),
  1472.         PANEL_LABEL_Y,        ATTR_ROW(row),
  1473.         ATTR_LIST,         host_attr,
  1474.         0);
  1475.       dDir_item[i] = panel_create_item(dest_panel[i], PANEL_TEXT,
  1476.            PANEL_LABEL_X,        ATTR_COL(2),
  1477.         PANEL_LABEL_Y,        ATTR_ROW(++row),
  1478.         PANEL_VALUE,    (char *)panel_get(sDir_item, PANEL_VALUE),
  1479.         ATTR_LIST,        dir_attr,
  1480.         0);
  1481.       if (strlen(def_dir))
  1482.     panel_set(dDir_item[i], PANEL_EVENT_PROC, display_dir_menu, 0);
  1483.         
  1484.       dLogin_item[i] = panel_create_item(dest_panel[i], PANEL_TEXT,
  1485.         ATTR_LIST,        login_attr,
  1486.         PANEL_EVENT_PROC,       hint_event_proc,
  1487.         0);
  1488.       dLoginDef_msg[i] = panel_create_item(dest_panel[i], PANEL_MESSAGE,
  1489.            PANEL_LABEL_X,         (int)panel_get(dLogin_item[i],
  1490.                             PANEL_VALUE_X),
  1491.         PANEL_LABEL_Y,         (int)panel_get(dLogin_item[i],
  1492.                             PANEL_VALUE_Y),
  1493.             PANEL_LABEL_STRING,  same_as_login,
  1494.         0);
  1495.  
  1496.       dFile_item[i] = panel_create_item(dest_panel[i], PANEL_TEXT,
  1497.            PANEL_LABEL_X,        ATTR_COL(2),
  1498.         PANEL_LABEL_Y,        ATTR_ROW(++row),
  1499.         ATTR_LIST,        file_attr,
  1500.         PANEL_EVENT_PROC,    hint_event_proc,
  1501.         0);
  1502.       dFileDef_msg[i] = panel_create_item(dest_panel[i], PANEL_MESSAGE,
  1503.            PANEL_LABEL_X,         (int)panel_get(dFile_item[i],
  1504.                             PANEL_VALUE_X),
  1505.         PANEL_LABEL_Y,         (int)panel_get(dFile_item[i],
  1506.                             PANEL_VALUE_Y),
  1507.             PANEL_LABEL_STRING,  (!conference)?SAME_AS_SRC:
  1508.                      (strlen(def_passwd))?SAME_AS_HERE:
  1509.                      SAME_AS_CONF,
  1510.         0);
  1511.  
  1512.       dPass_item[i] = panel_create_item(dest_panel[i], PANEL_TEXT,
  1513.         ATTR_LIST,        pass_attr,
  1514.         PANEL_EVENT_PROC,       hint_event_proc,
  1515.         0);
  1516.       dPassDef_msg[i] = panel_create_item(dest_panel[i], PANEL_MESSAGE,
  1517.            PANEL_LABEL_X,         (int)panel_get(dPass_item[i],
  1518.                             PANEL_VALUE_X),
  1519.         PANEL_LABEL_Y,         (int)panel_get(dPass_item[i],
  1520.                             PANEL_VALUE_Y),
  1521.             PANEL_LABEL_STRING,  (strlen(def_passwd))?same_as_pass:
  1522.                      SAME_AS_SRC,
  1523.         0);
  1524.       window_fit(dest_panel[i]);
  1525.       window_fit_width(dest_frame[i]);
  1526.  
  1527.       dStatus_sw[i] = window_create(dest_frame[i], TEXTSW,
  1528.          WIN_HEIGHT,        ATTR_ROW(8),
  1529.         TEXTSW_IGNORE_LIMIT,    TEXTSW_INFINITY,
  1530.            TEXTSW_READ_ONLY,     TRUE,
  1531.         0);
  1532.     
  1533.       window_fit(dStatus_sw[i]);
  1534.       window_fit(dest_frame[i]);
  1535.     }
  1536. } /* make_dest_frames */
  1537.  
  1538. static void
  1539. addDest_proc(item, value, event) 
  1540.    Panel_item item;
  1541.    unsigned int value;
  1542.    Event *event; 
  1543. {
  1544.    int i;
  1545.    boolean change;
  1546.  
  1547.    change = new_y_positions();
  1548.    for (i=0;i<max_dest;i++) 
  1549.       if ((1<<i & value) ||
  1550.       (empty_str((char *)panel_get(dShow_item, 
  1551.                        PANEL_CHOICE_STRING, i)) &&
  1552.        (int)window_get(dest_frame[i],WIN_SHOW))) {
  1553.      if (change || (prev_show_val < value))
  1554.         window_set(dest_frame[i], 
  1555.                WIN_SHOW,     TRUE, 
  1556.                WIN_X,        0,
  1557.                WIN_Y,        dFrame_y[i],
  1558.                0);
  1559.          }
  1560.       else
  1561.      close_dframe(i);
  1562.    prev_useHost_val = (int)panel_get(useDHost_item, PANEL_VALUE);
  1563.    prev_show_val = (int)panel_get(dShow_item, PANEL_VALUE);
  1564. } /* addDest_proc */
  1565.  
  1566. static void
  1567. newDest_proc(item, value, event) 
  1568.    Panel_item item;
  1569.    unsigned int value;
  1570.    Event *event; 
  1571. {
  1572.    int i;
  1573.    boolean change;
  1574.  
  1575.    change = new_y_positions();
  1576.    if (prev_useHost_val < value)
  1577.       for (i=0;i<max_dest;i++)
  1578.      if ((1<<i & value) == (prev_useHost_val ^ value)) {
  1579.         if (empty_str((char *)panel_get(dShow_item, 
  1580.                         PANEL_CHOICE_STRING, i)) &&
  1581.         !(int)window_get(dest_frame[i], WIN_SHOW)) {
  1582.            change = TRUE;
  1583.            window_set(dest_frame[i], WIN_SHOW, TRUE, 0);
  1584.            }
  1585.         break;
  1586.         }  
  1587.    if (change)
  1588.       for (i=0;i<max_dest;i++)
  1589.      if (window_get(dest_frame[i], WIN_SHOW))
  1590.         window_set(dest_frame[i], 
  1591.                WIN_SHOW,     TRUE, 
  1592.                WIN_X,        0,
  1593.                WIN_Y,        dFrame_y[i],
  1594.                0);
  1595.    prev_useHost_val = value;
  1596. } /* newDest_proc */
  1597.  
  1598. static void
  1599. param_proc(item, event)
  1600.    Panel_item item;
  1601.    Event *event; 
  1602. {
  1603.    if ((int)window_get(pFrame, WIN_SHOW))
  1604.       window_set(pFrame, WIN_SHOW, FALSE, 0);
  1605.    else
  1606.       window_set(pFrame, 
  1607.          WIN_SHOW,     TRUE, 
  1608.          WIN_X,        ATTR_COL(17),
  1609.          WIN_Y,        ATTR_ROW(2),
  1610.          0);
  1611. }
  1612.  
  1613. static void
  1614. create_param_frame()
  1615. {
  1616.    Window params;
  1617.    int row = 0;
  1618.  
  1619.    pFrame = window_create(tool_frame, FRAME,
  1620.            WIN_X,             ATTR_COL(17),
  1621.         WIN_Y,             ATTR_ROW(2),
  1622.            FRAME_LABEL,         "FTP Parameters",
  1623.         FRAME_SHOW_LABEL,    TRUE,
  1624.         FRAME_NO_CONFIRM,     TRUE,
  1625.         FRAME_DONE_PROC,     param_proc,
  1626.         0);
  1627.    params = window_create(pFrame, PANEL,
  1628.            PANEL_ITEM_X_GAP,    15,
  1629.         0);
  1630.         
  1631.    stru_item = panel_create_item(params, PANEL_CYCLE,
  1632.         PANEL_LABEL_X,          ATTR_COL(0),
  1633.         PANEL_LABEL_Y,          ATTR_ROW(row),
  1634.         ATTR_LIST,        stru_attr,
  1635.         0);
  1636.    mode_item = panel_create_item(params, PANEL_CYCLE,
  1637.         ATTR_LIST,              mode_attr,
  1638.         0);
  1639.    type_item = panel_create_item(params, PANEL_CYCLE,
  1640.            PANEL_LABEL_X,        ATTR_COL(0),
  1641.         PANEL_LABEL_Y,        ATTR_ROW(++row),
  1642.         ATTR_LIST,              type_attr,
  1643.         PANEL_VALUE,        type_choice(IMAGE),
  1644.         0);
  1645.  
  1646.    format_item = panel_create_item(params, PANEL_CYCLE,
  1647.         ATTR_LIST,              form_attr,
  1648.         PANEL_SHOW_ITEM,     FALSE,
  1649.                      /* because of type IMAGE */
  1650.         0);
  1651.    byteSize_item = panel_create_item(params, PANEL_TEXT,
  1652.         ATTR_LIST,              byte_attr,
  1653.            PANEL_LABEL_X,        (int)panel_get(format_item, 
  1654.                         PANEL_LABEL_X),
  1655.         PANEL_LABEL_Y,
  1656.                     (int)panel_get(format_item, 
  1657.                         PANEL_LABEL_Y),
  1658.         0);
  1659.    multiple_item = panel_create_item(params, PANEL_CYCLE,
  1660.            PANEL_LABEL_X,        ATTR_COL(0),
  1661.         PANEL_LABEL_Y,        ATTR_ROW(++row),
  1662.         ATTR_LIST,              mult_attr,
  1663.         0);
  1664.    append_item = panel_create_item(params, PANEL_CYCLE,
  1665.         ATTR_LIST,              app_attr,
  1666.         0);
  1667.    stou_item = panel_create_item(params, PANEL_CYCLE,
  1668.            PANEL_LABEL_X,        ATTR_COL(0),
  1669.         PANEL_LABEL_Y,        ATTR_ROW(++row),
  1670.         ATTR_LIST,              stou_attr,
  1671.         0);
  1672.    window_fit(params);
  1673.    window_fit(pFrame);
  1674. }/* create_param_frame */
  1675.  
  1676. static boolean
  1677. new_host(i)  /* i is the entry being checked */
  1678.    int i;
  1679. {
  1680.    int j;
  1681.    boolean value = TRUE;
  1682.  
  1683.    /* eliminate duplicate entry */
  1684.    for (j = i-1; j >= 0; j--) {
  1685.       if (!strcmp(hosts[i].str, hosts[j].str)) { /* they match */
  1686.      value = FALSE;
  1687.      break;
  1688.          }
  1689.       if (user_set_host[j] && 
  1690.       !strcmp(hosts[i].str, 
  1691.           (char *)panel_get(dHost_item[j], PANEL_VALUE))) {
  1692.       /* they match */
  1693.      value = FALSE;
  1694.      break;
  1695.          }
  1696.       }
  1697.    /* check validity of host name */
  1698.    if (value)
  1699.       if (!host_okay(hosts[i].str))
  1700.      value = FALSE;
  1701.  
  1702.    return(value);
  1703. } /* new_host */
  1704.  
  1705. static void
  1706. get_hosts()
  1707. {
  1708.    int i, j;
  1709.    char filename[100];
  1710.    FILE *listp;
  1711.  
  1712.    /* Read in current hosts list from file mbftp.confhosts */
  1713.    sprintf(filename,"%smbftp.confhosts", bftp_dir);
  1714.    if ((listp = fopen(filename, "r")) == NULL) {
  1715.       for (i=0; i<max_dest; i++)
  1716.       hosts[i].str[0]= '\0';
  1717.       }
  1718.    else {
  1719.       for (i=0; i<max_dest; ) {
  1720.      if (fgets(hosts[i].str, sizeof(hosts[i].str), listp) == NULL) {
  1721.         /* add the local host if needed */
  1722.         if (conference && !strlen(def_passwd)) {
  1723.            strcpy(hosts[i].str, def_hostname);
  1724.            if (new_host(i))
  1725.            i++;
  1726.          else
  1727.            hosts[i].str[0] = '\0';
  1728.            }
  1729.         /* clear out the rest of the entries */
  1730.         while (i<max_dest) {
  1731.          hosts[i].str[0]= '\0';
  1732.          i++;
  1733.              }
  1734.         fclose(listp);
  1735.         }
  1736.      else {
  1737.         /* get rid of line-feed */
  1738.         hosts[i].str[strlen(hosts[i].str)-1]= '\0';
  1739.         if (new_host(i))
  1740.            i++;
  1741.         else
  1742.            hosts[i].str[0] = '\0';
  1743.         }
  1744.          }
  1745.       }
  1746.    for (i = j = 0;i<max_dest && j<max_dest; i++) {
  1747.      if (!user_set_host[i]) {
  1748.         panel_set(dHost_item[i], PANEL_VALUE, hosts[j].str, 0);
  1749.         panel_set(dShow_item, PANEL_CHOICE_STRING, i, hosts[j].str, 0);
  1750.         set_status(i, " ");
  1751.         j++;
  1752.         }
  1753.        }
  1754. } /* get_hosts */                       
  1755.  
  1756. static void
  1757. close_proc()
  1758. {
  1759.    int i;
  1760.     
  1761.    for (i=0;i<max_dest;i++)
  1762.       close_dframe(i);
  1763.    prev_useHost_val = (int)panel_get(useDHost_item, PANEL_VALUE);
  1764.    prev_show_val = (int)panel_get(dShow_item, PANEL_VALUE);
  1765.    window_set(tool_frame, FRAME_CLOSED, TRUE, 0);
  1766. }
  1767.  
  1768. static void
  1769. quit_proc(item, event)
  1770.    Panel_item item;
  1771.    Event *event;
  1772. {
  1773.    int i;
  1774.    
  1775.    for (i=0;i<max_dest;i++)
  1776.       if (dest_pid[i])
  1777.      kill(dest_pid[i], SIGKILL);
  1778.       
  1779.    window_destroy(tool_frame);
  1780. }
  1781.  
  1782. static void
  1783. submit_proc(item, event)
  1784.    Panel_item item;
  1785.    Event *event;
  1786. {
  1787.    set_buttons(FALSE);
  1788.    window_set(pFrame, WIN_SHOW, FALSE, 0);
  1789.    make_submit_frame(&req, 40, 3, 
  1790.              (int)panel_get(verbose_item, PANEL_ITEM_X),
  1791.              (int)panel_get(verbose_item, PANEL_ITEM_Y));
  1792. }
  1793.  
  1794. static void
  1795. create_tool_panel()
  1796. {
  1797.    Menu menu;
  1798.    char conf_str[60];
  1799.    int i,
  1800.        bwidth = 8,
  1801.        row = 0;
  1802.  
  1803.    window_destroy(tool_panel);
  1804.  
  1805.    tool_panel = window_create(tool_frame, PANEL,
  1806.         WIN_X,            0,
  1807.         WIN_Y,            0,
  1808.            PANEL_ITEM_X_GAP,    15,
  1809.         0);
  1810.  
  1811.    if (conference) {
  1812.       sprintf(conf_str, "MBFTP Tool    ConfID: %s",
  1813.           strlen(def_dir)?def_dir:"not set ");
  1814.       conf_str[strlen(conf_str)-1] = '\0';
  1815.       window_set(tool_frame, FRAME_LABEL, conf_str, 0);
  1816.       }
  1817.    transferAll_item = panel_create_item(tool_panel, PANEL_BUTTON,
  1818.            PANEL_LABEL_X,        ATTR_COL(0),
  1819.         PANEL_LABEL_Y,        ATTR_ROW(0),
  1820.            PANEL_LABEL_IMAGE,
  1821.             panel_button_image(tool_panel, "Transfer", bwidth,0),
  1822.         PANEL_EVENT_PROC,    dummy_event_proc,
  1823.         PANEL_NOTIFY_PROC,    transfer_all,
  1824.         0);
  1825.    param_item = panel_create_item(tool_panel, PANEL_BUTTON,
  1826.            PANEL_LABEL_IMAGE,
  1827.             panel_button_image(tool_panel, "ShowParams", bwidth, 0),
  1828.         PANEL_EVENT_PROC,    dummy_event_proc,
  1829.         PANEL_NOTIFY_PROC,    param_proc,
  1830.         0);
  1831.    submitAll_item = panel_create_item(tool_panel, PANEL_BUTTON,
  1832.            PANEL_LABEL_IMAGE,
  1833.             panel_button_image(tool_panel, "Submit", bwidth, 0),
  1834.         PANEL_EVENT_PROC,    dummy_event_proc,
  1835.         PANEL_NOTIFY_PROC,    submit_proc,
  1836.         0);
  1837.         
  1838.    quit_item = panel_create_item(tool_panel, PANEL_BUTTON,
  1839.            PANEL_LABEL_X,        ATTR_COL(0),
  1840.         PANEL_LABEL_Y,        (ATTR_ROW(++row)+(row*8)),
  1841.            PANEL_LABEL_IMAGE,
  1842.             panel_button_image(tool_panel, "Quit", bwidth, 0),
  1843.         PANEL_EVENT_PROC,    dummy_event_proc,
  1844.         PANEL_NOTIFY_PROC,    quit_proc,
  1845.         0);
  1846.    if (conference) {
  1847.       if (strlen(def_passwd))
  1848.      dist_item = panel_create_item(tool_panel, PANEL_CYCLE,    
  1849.         PANEL_LABEL_STRING,     "Dist:",
  1850.         PANEL_CHOICE_STRINGS,   "Src->Here->Dsts",
  1851.                      "Here->Dsts",
  1852.                      0,
  1853.         PANEL_VALUE,            0,
  1854.         PANEL_DISPLAY_LEVEL,    PANEL_CURRENT,
  1855.         PANEL_EVENT_PROC,    dummy_event_proc,
  1856.         PANEL_NOTIFY_PROC,    dist_proc,
  1857.         0);
  1858.       }
  1859.    else {
  1860.       storage_item = panel_create_item(tool_panel, PANEL_BUTTON,
  1861.            PANEL_LABEL_IMAGE,
  1862.            panel_button_image(tool_panel, "RequestStorage", bwidth, 0),
  1863.         PANEL_EVENT_PROC,    dummy_event_proc,
  1864.         PANEL_NOTIFY_PROC,    rStorage_proc,
  1865.         0);
  1866.       init_rs_location(ATTR_COL(17), ATTR_ROW(8));
  1867.       }
  1868.  
  1869.    resetAll_item = panel_create_item(tool_panel, PANEL_BUTTON,
  1870.            PANEL_LABEL_X,        ATTR_COL(0),
  1871.         PANEL_LABEL_Y,        (ATTR_ROW(++row)+(row*8)),
  1872.            PANEL_LABEL_IMAGE,
  1873.             panel_button_image(tool_panel, "Reset", bwidth, 0),
  1874.         PANEL_EVENT_PROC,    dummy_event_proc,
  1875.         PANEL_NOTIFY_PROC,    reset_all,
  1876.         0);
  1877.    verbose_item = panel_create_item(tool_panel, PANEL_CYCLE,
  1878.            PANEL_LABEL_STRING,    "Verbose:",
  1879.         PANEL_CHOICE_STRINGS,     "FALSE", "TRUE", 0,
  1880.         PANEL_VALUE,        0,
  1881.         PANEL_DISPLAY_LEVEL,    PANEL_CURRENT,
  1882.         PANEL_EVENT_PROC,    dummy_event_proc,
  1883.         0);
  1884.  
  1885.    row++;
  1886.    src_msg = panel_create_item(tool_panel, PANEL_MESSAGE,
  1887.            PANEL_LABEL_X,          ATTR_COL(0),
  1888.         PANEL_LABEL_Y,          ATTR_ROW(++row),
  1889.         PANEL_LABEL_STRING,     "Src --",
  1890.         0);
  1891.    sDir_item = panel_create_item(tool_panel, PANEL_TEXT,
  1892.            PANEL_LABEL_X,        ATTR_COL(2),
  1893.         PANEL_LABEL_Y,        ATTR_ROW(++row),
  1894.         PANEL_VALUE,         def_dir,
  1895.         ATTR_LIST,        dir_attr,
  1896.         0);
  1897.    if (strlen(def_dir))
  1898.       panel_set(sDir_item, PANEL_EVENT_PROC, display_dir_menu, 0);
  1899.  
  1900.    sFile_item = panel_create_item(tool_panel, PANEL_TEXT,
  1901.            PANEL_LABEL_X,        ATTR_COL(2),
  1902.         PANEL_LABEL_Y,        ATTR_ROW(++row),
  1903.         ATTR_LIST,        file_attr,
  1904.         PANEL_EVENT_PROC,       sFile_event_proc,
  1905.         0);
  1906.    sHost_item = panel_create_item(tool_panel, PANEL_TEXT,
  1907.            PANEL_LABEL_X,        ATTR_COL(2),
  1908.         PANEL_LABEL_Y,        ATTR_ROW(++row),
  1909.         ATTR_LIST,         host_attr,
  1910.         0);
  1911.    sLogin_item = panel_create_item(tool_panel, PANEL_TEXT,
  1912.            PANEL_LABEL_X,        ATTR_COL(2),
  1913.         PANEL_LABEL_Y,        ATTR_ROW(++row),
  1914.         ATTR_LIST,        login_attr,
  1915.         0);
  1916.    sPass_item = panel_create_item(tool_panel, PANEL_TEXT,
  1917.            PANEL_LABEL_X,        ATTR_COL(2),
  1918.         PANEL_LABEL_Y,        ATTR_ROW(++row),
  1919.         ATTR_LIST,        pass_attr,
  1920.         0);
  1921.    if (strlen(def_passwd)) {
  1922.       panel_set(sPass_item, PANEL_EVENT_PROC, hint_event_proc, 0);
  1923.       sPassDef_msg = panel_create_item(tool_panel, PANEL_MESSAGE,
  1924.            PANEL_LABEL_X,         (int)panel_get(sPass_item,
  1925.                             PANEL_VALUE_X),
  1926.         PANEL_LABEL_Y,         (int)panel_get(sPass_item,
  1927.                             PANEL_VALUE_Y),
  1928.             PANEL_LABEL_STRING,  same_as_pass,
  1929.         0);
  1930.       }
  1931.    if (conference) {
  1932.       conf_msg = panel_create_item(tool_panel, PANEL_MESSAGE,
  1933.            PANEL_LABEL_X,        ATTR_COL(0),
  1934.         PANEL_LABEL_Y,        ATTR_ROW(++row),
  1935.         PANEL_LABEL_STRING,    "Here --",
  1936.         0);
  1937.       cFile_item = panel_create_item(tool_panel, PANEL_TEXT,
  1938.            PANEL_LABEL_X,        ATTR_COL(2),
  1939.         PANEL_LABEL_Y,        ATTR_ROW(++row),
  1940.         ATTR_LIST,        file_attr,
  1941.         PANEL_EVENT_PROC,       hint_event_proc,
  1942.         0);
  1943.       cFileDef_msg = panel_create_item(tool_panel, PANEL_MESSAGE,
  1944.            PANEL_LABEL_X,          (int)panel_get(cFile_item, PANEL_VALUE_X),
  1945.         PANEL_LABEL_Y,          (int)panel_get(cFile_item, PANEL_VALUE_Y),
  1946.         PANEL_LABEL_STRING,    SAME_AS_SRC,
  1947.         0);
  1948.       }
  1949.  
  1950.    switch (max_dest) {
  1951.    case 4:
  1952.      useDHost_item = panel_create_item(tool_panel, PANEL_TOGGLE,
  1953.             PANEL_LABEL_STRING,     "Dsts -- ", 
  1954.         PANEL_SHOW_MENU,    FALSE,
  1955.             PANEL_LABEL_X,        ATTR_COL(0),
  1956.             PANEL_LABEL_Y,          ATTR_ROW(++row),
  1957.         PANEL_LAYOUT,        PANEL_VERTICAL,
  1958.         PANEL_CHOICE_STRINGS,    " ",
  1959.                     " ",
  1960.                     " ",
  1961.                     " ",
  1962.                     0,
  1963.         PANEL_MARK_XS,        ATTR_COL(10),
  1964.                     ATTR_COL(10),
  1965.                     ATTR_COL(10),
  1966.                     ATTR_COL(10),
  1967.                     0,
  1968.         PANEL_CHOICE_XS,    ATTR_COL(0),
  1969.                     ATTR_COL(0),
  1970.                     ATTR_COL(0),
  1971.                     ATTR_COL(0),
  1972.                     0,
  1973.         PANEL_NOTIFY_PROC,    newDest_proc,
  1974.         PANEL_EVENT_PROC,    dummy_event_proc,
  1975.            0);
  1976.      dShow_item = panel_create_item(tool_panel, PANEL_TOGGLE,
  1977.            PANEL_LABEL_STRING,     "",
  1978.         PANEL_SHOW_MENU,    FALSE,
  1979.         PANEL_LAYOUT,        PANEL_VERTICAL,
  1980.         PANEL_FEEDBACK,        PANEL_INVERTED,
  1981.         PANEL_CHOICE_STRINGS,    "",
  1982.                     "",
  1983.                       "",
  1984.                     "",
  1985.                     0,
  1986.         PANEL_CHOICE_XS,    ATTR_COL(13),
  1987.                     ATTR_COL(13),
  1988.                     ATTR_COL(13),
  1989.                     ATTR_COL(13),
  1990.                     0,
  1991.         PANEL_CHOICE_YS,
  1992.             (int)panel_get(useDHost_item, PANEL_CHOICE_Y, 0),
  1993.             (int)panel_get(useDHost_item, PANEL_CHOICE_Y, 1),
  1994.             (int)panel_get(useDHost_item, PANEL_CHOICE_Y, 2),
  1995.             (int)panel_get(useDHost_item, PANEL_CHOICE_Y, 3),
  1996.                     0,
  1997.         PANEL_NOTIFY_PROC,    addDest_proc,
  1998.         PANEL_EVENT_PROC,    dummy_event_proc,
  1999.            0);
  2000.      break;
  2001.    case 3:
  2002.      useDHost_item = panel_create_item(tool_panel, PANEL_TOGGLE,
  2003.             PANEL_LABEL_STRING,     "Destinations", 
  2004.         PANEL_SHOW_MENU,    FALSE,
  2005.             PANEL_LABEL_X,        ATTR_COL(0),
  2006.             PANEL_LABEL_Y,          ATTR_ROW(++row),
  2007.         PANEL_LAYOUT,        PANEL_VERTICAL,
  2008.         PANEL_CHOICE_STRINGS,    " ",
  2009.                     " ",
  2010.                     " ",
  2011.                     0,
  2012.         PANEL_MARK_XS,        ATTR_COL(10),
  2013.                     ATTR_COL(10),
  2014.                     ATTR_COL(10),
  2015.                     0,
  2016.         PANEL_CHOICE_XS,    ATTR_COL(0),
  2017.                     ATTR_COL(0),
  2018.                     ATTR_COL(0),
  2019.                     0,
  2020.         PANEL_NOTIFY_PROC,    newDest_proc,
  2021.         PANEL_EVENT_PROC,    dummy_event_proc,
  2022.            0);
  2023.      dShow_item = panel_create_item(tool_panel, PANEL_TOGGLE,
  2024.            PANEL_LABEL_STRING,     "",
  2025.         PANEL_SHOW_MENU,    FALSE,
  2026.         PANEL_LAYOUT,        PANEL_VERTICAL,
  2027.         PANEL_FEEDBACK,        PANEL_INVERTED,
  2028.         PANEL_CHOICE_STRINGS,    "",
  2029.                     "",
  2030.                       "",
  2031.                     0,
  2032.         PANEL_CHOICE_XS,    ATTR_COL(13),
  2033.                     ATTR_COL(13),
  2034.                     ATTR_COL(13),
  2035.                     0,
  2036.         PANEL_CHOICE_YS,
  2037.             (int)panel_get(useDHost_item, PANEL_CHOICE_Y, 0),
  2038.             (int)panel_get(useDHost_item, PANEL_CHOICE_Y, 1),
  2039.             (int)panel_get(useDHost_item, PANEL_CHOICE_Y, 2),
  2040.                     0,
  2041.         PANEL_NOTIFY_PROC,    addDest_proc,
  2042.         PANEL_EVENT_PROC,    dummy_event_proc,
  2043.            0);
  2044.    }
  2045.  
  2046.    window_fit(tool_panel);
  2047.    window_fit(tool_frame);
  2048.  
  2049.    /* initialize the destination hosts */
  2050.    make_dest_frames();
  2051.  
  2052.    get_hosts();
  2053.    /* set the values for useDHost_item, and decide whether to show
  2054.       sHost_item, sLogin_item, and sPass_item */
  2055.    if (!conference || !strlen(def_passwd))
  2056.       src_to_dsts();
  2057.    else
  2058.       dist_proc(dist_item, (int)panel_get(dist_item, PANEL_VALUE), 0);
  2059.  
  2060.    menu = (Menu)window_get(tool_frame, WIN_MENU);
  2061.    menu_set((Menu_item)menu_find(menu, MENU_STRING, "Close", 0),
  2062.         MENU_ACTION_PROC, close_proc, 0);
  2063.    menu_set((Menu_item)menu_find(menu, MENU_STRING, "Quit", 0),
  2064.         MENU_ACTION_PROC, quit_proc, 0);
  2065.  
  2066.    toolsetup = TRUE;
  2067. } /* create_tool_panel */
  2068.  
  2069. static void
  2070. copy_password()
  2071. {
  2072.    struct passwd *pwd;
  2073.    char *namep;
  2074.  
  2075.    strcpy(def_passwd, (char *)panel_get(pPass_item, PANEL_VALUE));
  2076.    setpwent();
  2077.    if (empty_str(def_passwd) || (pwd = getpwnam(def_user)) == NULL) {
  2078.      def_passwd[0] = '\0';
  2079.      create_tool_panel();
  2080.      create_param_frame();
  2081.      panel_set(sDir_item, PANEL_VALUE, "", 0);
  2082.          }
  2083.    else {
  2084.      namep = crypt(def_passwd, pwd->pw_passwd);
  2085.      if (!strcmp(namep, pwd->pw_passwd)) {
  2086.         /* password is valid */
  2087.         create_tool_panel();
  2088.         create_param_frame();
  2089.             }
  2090.      else {
  2091.             panel_set(pPass_item, PANEL_VALUE, "", 0);
  2092.         panel_set(pMsg_item, 
  2093.               PANEL_LABEL_STRING, 
  2094.                   "   Password incorrect; re-enter, or type <RETURN>.", 
  2095.               0);
  2096.         }
  2097.          }
  2098.    endpwent();
  2099. } /* copy_password */
  2100.  
  2101. static void
  2102. get_word(item, event)
  2103.    Panel_item item;
  2104.    Event *event;
  2105. {
  2106.   /* return is the same as "Done" */
  2107.   if ('\015' == (char)event_id(event))
  2108.      copy_password();
  2109.   else
  2110.      no_spaces(item, event);
  2111. }
  2112.  
  2113. static char dir[100];
  2114.  
  2115. /* Read in the default directory from file mbftp.confid */
  2116. char *
  2117. get_confid()
  2118. {
  2119.    char temp[100];
  2120.    int i;
  2121.    FILE *listp;
  2122.  
  2123.    dir[0] = '\0';
  2124.    if (conference) {
  2125.       sprintf(temp,"%smbftp.confid", bftp_dir);
  2126.       if ((listp = fopen(temp, "r")) != NULL) {
  2127.      if (fgets(dir, sizeof(dir), listp) != NULL) {
  2128.         if (dir[strlen(dir)-1] == '\n')
  2129.            dir[strlen(dir)-1]= '\0';
  2130.         if (dir[strlen(dir)-1] != '/')
  2131.            strcat(dir, "/");
  2132.         /* check validity of directory name */
  2133.         sprintf(temp,"%s/%s",getenv("HOME"), dir);
  2134.         if ((i = open(temp, O_RDONLY)) < 0)
  2135.            dir[0]= '\0';
  2136.         else
  2137.            close(i);
  2138.         }
  2139.      fclose(listp);
  2140.          }
  2141.       }
  2142.    return(dir);
  2143. } /* get_confid */        
  2144.  
  2145. static Notify_value
  2146. read_init_files(me, signal, when)
  2147.    int *me;
  2148.    int signal;
  2149.    Notify_signal_mode when;
  2150. {
  2151.    char conf_str[60], *cp, *src;
  2152.    int i;
  2153.  
  2154.    if (toolsetup) {
  2155.       cp = get_confid();
  2156.       if (!strlen(def_dir)) {
  2157.      if (strlen(cp)) {
  2158.         /* add dir_menu */
  2159.         init_dir_menu();
  2160.         panel_set(sDir_item, PANEL_EVENT_PROC, display_dir_menu, 0);
  2161.         for (i=0;i<max_dest;i++)
  2162.            panel_set(dDir_item[i], 
  2163.                      PANEL_EVENT_PROC, display_dir_menu, 
  2164.              0);
  2165.         }
  2166.          }
  2167.       else
  2168.      if (!strlen(cp)) {
  2169.         /* delete menu */
  2170.         panel_set(sDir_item, PANEL_EVENT_PROC, no_spaces, 0);
  2171.         for (i=0;i<max_dest;i++)
  2172.            panel_set(dDir_item[i], PANEL_EVENT_PROC, no_spaces, 0);
  2173.         menu_destroy(dir_menu);
  2174.         }
  2175.  
  2176.       /* if the current dir is the same as the old default, update it */
  2177.       if (conference && strlen(def_passwd)) {
  2178.     if (!strcmp(def_dir, (char *)panel_get(sDir_item, PANEL_VALUE)) &&
  2179.          (int)panel_get(dist_item, PANEL_VALUE)) /* Here->Dsts */
  2180.            panel_set(sDir_item, PANEL_VALUE, cp, 0);
  2181.     for (i=0;i<max_dest;i++) 
  2182.       if (!strcmp(def_dir, (char *)panel_get(dDir_item[i], PANEL_VALUE)))
  2183.         panel_set(dDir_item[i], PANEL_VALUE, cp, 0);
  2184.       }
  2185.  
  2186.       strcpy(def_dir, cp);
  2187.       if (conference) {
  2188.      sprintf(conf_str, "MBFTP Tool    ConfID: %s",
  2189.          strlen(def_dir)?def_dir:"not set ");
  2190.      conf_str[strlen(conf_str)-1] = '\0';
  2191.      window_set(tool_frame, FRAME_LABEL, conf_str, 0);
  2192.          }
  2193.  
  2194.       get_hosts();
  2195.       /* set the values for useDHost_item */
  2196.       if (conference && strlen(def_passwd))
  2197.     switch ((int)panel_get(dist_item, PANEL_VALUE)) {
  2198.     case 1: /* Here->Dsts */
  2199.         for (i=0;i<max_dest;i++) {
  2200.           cp = (char *)panel_get(dShow_item, PANEL_CHOICE_STRING, i);
  2201.           panel_set(useDHost_item, 
  2202.                  PANEL_TOGGLE_VALUE,     i, 
  2203.              ((!empty_str(cp)) && !host_matches(cp, def_hostname))
  2204.                 ?TRUE:FALSE, 
  2205.                  0);
  2206.           }
  2207.         break;
  2208.       case 0: /* Src->Here->Dsts */
  2209.          src = (char *)panel_get(sHost_item, PANEL_VALUE);
  2210.          for (i=0;i<max_dest;i++) {
  2211.             cp = (char *)panel_get(dShow_item, PANEL_CHOICE_STRING, i);
  2212.         panel_set(useDHost_item, 
  2213.                  PANEL_TOGGLE_VALUE,     i, 
  2214.              ((!empty_str(cp)) && !host_matches(cp, def_hostname) &&
  2215.               !host_matches(cp, src))
  2216.                 ?TRUE:FALSE, 
  2217.                  0);
  2218.             }
  2219.       }
  2220.       else { /* Src->Dsts */
  2221.      src = (char *)panel_get(sHost_item, PANEL_VALUE);
  2222.      for (i=0;i<max_dest;i++) {
  2223.        cp = (char *)panel_get(dShow_item, PANEL_CHOICE_STRING, i);
  2224.        panel_set(useDHost_item,
  2225.              PANEL_TOGGLE_VALUE,     i,
  2226.              ((!empty_str(cp)) && !host_matches(cp, src))?TRUE:FALSE,
  2227.              0);
  2228.        }
  2229.          }
  2230.     }
  2231.    prev_useHost_val = (int)panel_get(useDHost_item, PANEL_VALUE);
  2232.  
  2233.    return(NOTIFY_IGNORED);
  2234. } /* read_init_files */
  2235.  
  2236. /* Notify Proc */
  2237.  
  2238. password_done(item, value, event)
  2239.         Panel_item item;
  2240.         unsigned int value;
  2241.         Event *event;
  2242. {
  2243.    copy_password();
  2244. }
  2245.  
  2246. static void
  2247. tool_help(name)
  2248.    char *name;
  2249. {
  2250.    fprintf(stderr,"Multiple-site Background File Transfer Program\n\n");
  2251.    frame_cmdline_help(name);
  2252. }
  2253.  
  2254. main(argc, argv)
  2255.    int argc;
  2256.    char **argv;
  2257. {
  2258.    int  client, 
  2259.         tempargc = argc;
  2260.    char **tempargv = argv;
  2261.  
  2262.    while (--tempargc > 0 && *++tempargv)
  2263.       if (!strncmp("-c", *tempargv, 2)) {
  2264.      conference = TRUE;
  2265.      break;
  2266.          }
  2267.  
  2268.    (void)notify_set_signal_func(&client, read_init_files, SIGUSR1, NOTIFY_SYNC);
  2269.  
  2270.    init_help();
  2271.  
  2272.    /* if the table size is small, cut back to 3 destinations */
  2273.    max_dest = (getdtablesize() > 32)? MAX_DEST: 3;
  2274.  
  2275.    init_user();
  2276.    if (strlen(def_user)) {
  2277.       sprintf(same_as_login,"(default is \"%s\")", def_user);
  2278.       sprintf(same_as_pass, "(password for \"%s\")", def_user);
  2279.       }
  2280.    else {
  2281.       strcpy(same_as_login, "(same as current login)");
  2282.       sprintf(same_as_pass, same_as_login);
  2283.       }
  2284.  
  2285.    init_req(&req);
  2286.    init_src_file_menu();
  2287.    init_login_menu();
  2288.    init_passw_menu();
  2289.    init_host_menu();
  2290.    init_attr_lists();
  2291.  
  2292.    strcpy(def_dir, get_confid());
  2293.    if (strlen(def_dir))
  2294.       init_dir_menu();
  2295.  
  2296.    /* create tool frame */
  2297.    tool_frame = window_create(NULL, FRAME,
  2298.            FRAME_LABEL,         "MBFTP Tool",
  2299.         FRAME_ICON,          &bftp_icon, 
  2300.         FRAME_CMDLINE_HELP_PROC, tool_help,
  2301.         FRAME_ARGS,        argc, argv,
  2302.         WIN_ERROR_MSG,        "Can't create window.",
  2303.         FRAME_NO_CONFIRM,     TRUE,
  2304.         0);
  2305.    tool_panel = window_create(tool_frame, PANEL,
  2306.            PANEL_ITEM_X_GAP,    15,
  2307.         0);
  2308.  
  2309.    /* create preliminary fields */
  2310.    pPass_item = panel_create_item(tool_panel, PANEL_TEXT,
  2311.        PANEL_LABEL_STRING,
  2312.         "MBFTPTool Initialization -- Enter default (local) password: ",
  2313.     PANEL_VALUE,        "",
  2314.     PANEL_EVENT_PROC,    get_word,
  2315.     PANEL_VALUE_DISPLAY_LENGTH, 2,
  2316.     PANEL_MASK_CHAR,    ' ',
  2317.     0);
  2318.    pDone_item =  panel_create_item(tool_panel, PANEL_BUTTON,
  2319.        PANEL_LABEL_X,        ATTR_COL(0),
  2320.     PANEL_LABEL_Y,        ATTR_ROW(1),
  2321.        PANEL_LABEL_IMAGE, panel_button_image(tool_panel, "Done", 4, 0),
  2322.     PANEL_NOTIFY_PROC,     password_done,
  2323.     PANEL_EVENT_PROC,    dummy_event_proc,
  2324.     0);
  2325.    pMsg_item = panel_create_item(tool_panel, PANEL_MESSAGE,
  2326.     PANEL_LABEL_STRING,     " ",
  2327.     0);
  2328.                  
  2329.    window_fit(tool_panel);
  2330.    window_fit(tool_frame);
  2331.  
  2332.    window_main_loop(tool_frame);
  2333.    exit(0);
  2334. }
  2335.